"""
Flask Web 应用
提供数据可视化和系统管理界面
"""

import logging
import json
from flask import Flask, render_template, jsonify, request
from datetime import datetime, timedelta
from typing import Dict, Any, Optional, List

# 全局变量，用于访问其他服务
data_engine = None
storage_service = None
alarm_service = None
scheduler_service = None

def create_app(engine=None, storage=None, alarm=None, scheduler=None, config: Dict[str, Any] = None) -> Flask:
    """创建Flask应用"""
    app = Flask(__name__)
    
    # 设置默认配置
    app.config['SECRET_KEY'] = 'dev-secret-key-change-in-production'
    app.config['DEBUG'] = False
    app.config['TESTING'] = False
    
    # 更新用户配置
    if config:
        app.config.update(config)
    
    # 设置服务引用
    set_services(engine, storage, alarm, scheduler)
    
    # 注册路由
    register_routes(app)
    
    return app

def set_services(engine, storage, alarm, scheduler):
    """设置服务引用"""
    global data_engine, storage_service, alarm_service, scheduler_service
    data_engine = engine
    storage_service = storage
    alarm_service = alarm
    scheduler_service = scheduler

def register_routes(app: Flask):
    """注册路由"""
    
    @app.route('/')
    def index():
        """主页"""
        return render_template('index.html')
    
    @app.route('/dashboard')
    def dashboard():
        """仪表盘页面"""
        return render_template('dashboard.html')
    
    @app.route('/status-test')
    def status_test():
        """系统状态测试页面"""
        return render_template('status_test.html')
    
    @app.route('/device-manager')
    def device_manager():
        """设备配置管理页面"""
        return render_template('device_manager.html')
    
    @app.route('/device-config')
    def device_config():
        """设备配置页面"""
        return render_template('device_config.html')
    
    @app.route('/api/devices')
    def get_devices():
        """获取设备列表"""
        try:
            if data_engine:
                devices = data_engine.get_device_info()
                return jsonify({
                    'success': True,
                    'data': devices
                })
            else:
                return jsonify({
                    'success': True,
                    'data': []
                })
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/device/<device_name>/status')
    def get_device_status(device_name: str):
        """获取设备状态"""
        try:
            if data_engine:
                status = data_engine.get_device_status(device_name)
                return jsonify({
                    'success': True,
                    'data': status
                })
            else:
                return jsonify({
                    'success': False,
                    'error': '数据引擎未初始化'
                }), 503
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/device/<device_name>/data')
    def get_device_data(device_name: str):
        """获取设备实时数据"""
        try:
            if data_engine:
                data = data_engine.get_latest_data(device_name)
                return jsonify({
                    'success': True,
                    'data': data
                })
            else:
                return jsonify({
                    'success': False,
                    'error': '数据引擎未初始化'
                }), 503
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/device/<device_name>/history')
    def get_device_history(device_name: str):
        """获取设备历史数据"""
        try:
            # 获取查询参数
            hours = request.args.get('hours', default=24, type=int)
            tag_name = request.args.get('tag', default=None)
            
            end_time = datetime.now()
            start_time = end_time - timedelta(hours=hours)
            
            if storage_service:
                history_data = storage_service.query_historical_data(
                    device_name=device_name,
                    tag_name=tag_name,
                    start_time=start_time,
                    end_time=end_time
                )
                
                return jsonify({
                    'success': True,
                    'data': history_data
                })
            else:
                return jsonify({
                    'success': False,
                    'error': '存储服务未初始化'
                }), 503
                
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/alarms')
    def get_alarms():
        """获取报警信息"""
        try:
            if alarm_service:
                active_alarms = alarm_service.get_active_alarms()
                alarm_history = alarm_service.get_alarm_history(limit=50)
                
                # 转换为可序列化的格式
                active_data = []
                for alarm in active_alarms:
                    active_data.append({
                        'id': alarm.id,
                        'device_name': alarm.device_name,
                        'tag_name': alarm.tag_name,
                        'level': alarm.level.value,
                        'message': alarm.message,
                        'value': alarm.value,
                        'timestamp': alarm.timestamp.isoformat(),
                        'acknowledged': alarm.acknowledged
                    })
                
                history_data = []
                for alarm in alarm_history:
                    history_data.append({
                        'id': alarm.id,
                        'device_name': alarm.device_name,
                        'tag_name': alarm.tag_name,
                        'level': alarm.level.value,
                        'message': alarm.message,
                        'value': alarm.value,
                        'timestamp': alarm.timestamp.isoformat(),
                        'acknowledged': alarm.acknowledged
                    })
                
                return jsonify({
                    'success': True,
                    'data': {
                        'active': active_data,
                        'history': history_data
                    }
                })
            else:
                return jsonify({
                    'success': True,
                    'data': {
                        'active': [],
                        'history': []
                    }
                })
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/alarm/<alarm_id>/acknowledge', methods=['POST'])
    def acknowledge_alarm(alarm_id: str):
        """确认报警"""
        try:
            if alarm_service:
                acknowledged_by = request.json.get('acknowledged_by', 'web_user')
                success = alarm_service.acknowledge_alarm(alarm_id, acknowledged_by)
                
                return jsonify({
                    'success': success,
                    'message': '报警已确认' if success else '确认失败'
                })
            else:
                return jsonify({
                    'success': False,
                    'error': '报警服务未初始化'
                }), 503
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/system/status')
    def get_system_status():
        """获取系统状态"""
        try:
            status = {
                'timestamp': datetime.now().isoformat(),
                'engine': None,
                'storage': None,
                'alarm': None,
                'scheduler': None,
                'services_status': {
                    'engine_available': data_engine is not None,
                    'storage_available': storage_service is not None,
                    'alarm_available': alarm_service is not None,
                    'scheduler_available': scheduler_service is not None
                }
            }
            
            # 安全地获取引擎统计信息
            if data_engine:
                try:
                    engine_stats = data_engine.get_statistics()
                    # 确保datetime对象被序列化
                    if 'last_collection_time' in engine_stats and engine_stats['last_collection_time']:
                        if isinstance(engine_stats['last_collection_time'], datetime):
                            engine_stats['last_collection_time'] = engine_stats['last_collection_time'].isoformat()
                    status['engine'] = engine_stats
                except Exception as e:
                    status['engine'] = {'error': f'获取引擎统计失败: {str(e)}'}
            
            # 安全地获取存储统计信息
            if storage_service:
                try:
                    status['storage'] = storage_service.get_statistics()
                except Exception as e:
                    status['storage'] = {'error': f'获取存储统计失败: {str(e)}'}
            
            # 安全地获取报警统计信息
            if alarm_service:
                try:
                    status['alarm'] = alarm_service.get_statistics()
                except Exception as e:
                    status['alarm'] = {'error': f'获取报警统计失败: {str(e)}'}
            
            # 安全地获取调度统计信息
            if scheduler_service:
                try:
                    status['scheduler'] = scheduler_service.get_statistics()
                except Exception as e:
                    status['scheduler'] = {'error': f'获取调度统计失败: {str(e)}'}
            
            return jsonify({
                'success': True,
                'data': status
            })
        except Exception as e:
            app.logger.error(f"系统状态API异常: {e}")
            return jsonify({
                'success': False,
                'error': f'获取系统状态失败: {str(e)}'
            }), 500
    
    @app.route('/api/tasks')
    def get_tasks():
        """获取任务列表"""
        try:
            if scheduler_service:
                tasks = scheduler_service.get_all_tasks()
                return jsonify({
                    'success': True,
                    'data': tasks
                })
            else:
                return jsonify({
                    'success': True,
                    'data': []
                })
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/task/<task_id>/pause', methods=['POST'])
    def pause_task(task_id: str):
        """暂停任务"""
        try:
            if scheduler_service:
                success = scheduler_service.pause_task(task_id)
                return jsonify({
                    'success': success,
                    'message': '任务已暂停' if success else '暂停失败'
                })
            else:
                return jsonify({
                    'success': False,
                    'error': '调度服务未初始化'
                }), 503
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/task/<task_id>/resume', methods=['POST'])
    def resume_task(task_id: str):
        """恢复任务"""
        try:
            if scheduler_service:
                success = scheduler_service.resume_task(task_id)
                return jsonify({
                    'success': success,
                    'message': '任务已恢复' if success else '恢复失败'
                })
            else:
                return jsonify({
                    'success': False,
                    'error': '调度服务未初始化'
                }), 503
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/device/test-connection', methods=['POST'])
    def test_device_connection():
        """测试设备连接"""
        try:
            config = request.json
            if not config:
                return jsonify({
                    'success': False,
                    'error': '配置参数缺失'
                }), 400
            
            # 这里应该实现实际的连接测试逻辑
            # 为了演示，我们返回一个模拟结果
            device_name = config.get('name', 'unknown')
            protocol = config.get('protocol', 'unknown')
            
            return jsonify({
                'success': True,
                'message': f'设备 {device_name} ({protocol}) 连接测试成功',
                'connection_time': '150ms',
                'status': 'online'
            })
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500

    @app.route('/api/opcua/browse-nodes', methods=['POST'])
    def browse_opcua_nodes():
        """浏览OPC UA服务器节点"""
        try:
            config = request.json
            if not config:
                return jsonify({
                    'success': False,
                    'error': '配置参数缺失'
                }), 400
            
            endpoint = config.get('endpoint')
            security_policy = config.get('security_policy', 'None')
            username = config.get('username')
            password = config.get('password')
            
            if not endpoint:
                return jsonify({
                    'success': False,
                    'error': '请提供OPC UA服务器端点'
                }), 400
            
            # 导入OPC UA客户端库（使用asyncua）
            try:
                from asyncua import Client, ua
                import asyncio
            except ImportError:
                return jsonify({
                    'success': False,
                    'error': 'OPC UA客户端库未安装，请执行: pip install asyncua'
                }), 500
            
            # 运行异步浏览函数
            try:
                nodes = asyncio.run(_async_browse_opcua_nodes(endpoint, security_policy, username, password))
                return jsonify({
                    'success': True,
                    'data': {
                        'endpoint': endpoint,
                        'nodes': nodes,
                        'total_nodes': len(nodes)
                    }
                })
            except Exception as e:
                return jsonify({
                    'success': False,
                    'error': f'浏览OPC UA节点失败: {str(e)}'
                }), 500
                
        except Exception as e:
            return jsonify({
                'success': False,
                'error': f'浏览OPC UA节点失败: {str(e)}'
            }), 500
    
    async def _async_browse_opcua_nodes(endpoint, security_policy='None', username=None, password=None):
        """异步浏览OPC UA服务器节点"""
        from asyncua import Client, ua
        
        client = Client(url=endpoint)
        
        try:
            # 设置安全策略（如果需要）
            if security_policy != 'None':
                # 根据需要配置安全策略
                pass
            
            # 设置用户认证
            if username and password:
                # asyncua使用不同的认证方式
                client.set_user(username)
                client.set_password(password)
            
            # 连接到服务器
            await client.connect()
            
            # 获取Objects节点
            objects = client.get_objects_node()
            
            # 浏览节点函数
            async def browse_node(node, max_depth=3, current_depth=0):
                """递归浏览节点"""
                if current_depth >= max_depth:
                    return []
                
                nodes = []
                try:
                    children = await node.get_children()
                    for child in children:
                        try:
                            # 获取节点信息
                            node_id = child.nodeid
                            browse_name = await child.read_browse_name()
                            display_name = await child.read_display_name()
                            
                            # 尝试获取数据类型
                            try:
                                data_type = await child.read_data_type()
                                data_type_str = str(data_type)
                            except:
                                data_type_str = "Unknown"
                            
                            # 检查是否是变量节点
                            try:
                                node_class = await child.read_node_class()
                                is_variable = node_class == ua.NodeClass.Variable
                            except:
                                is_variable = False
                            
                            node_info = {
                                'node_id': str(node_id),
                                'browse_name': str(browse_name),
                                'display_name': str(display_name.Text if hasattr(display_name, 'Text') else display_name),
                                'data_type': data_type_str,
                                'is_variable': is_variable,
                                'path': f"{str(browse_name)}",
                                'children': []
                            }
                            
                            # 如果是变量节点，尝试读取当前值
                            if is_variable:
                                try:
                                    value = await child.read_value()
                                    node_info['current_value'] = str(value)
                                except:
                                    node_info['current_value'] = "无法读取"
                            
                            # 递归获取子节点
                            if current_depth < max_depth - 1:
                                node_info['children'] = await browse_node(child, max_depth, current_depth + 1)
                            
                            nodes.append(node_info)
                            
                        except Exception as e:
                            # 跳过无法访问的节点
                            continue
                            
                except Exception as e:
                    # 跳过无法浏览的节点
                    pass
                
                return nodes
            
            # 浏览Objects节点下的所有子节点
            nodes = await browse_node(objects, max_depth=4)
            return nodes
            
        finally:
            await client.disconnect()
    
    @app.route('/api/device/config', methods=['POST'])
    def save_device_config():
        """保存单个设备配置"""
        try:
            device_config = request.json
            if not device_config:
                return jsonify({
                    'success': False,
                    'error': '配置参数缺失'
                }), 400
            
            # 添加调试信息
            app.logger.debug(f"接收到设备配置: {json.dumps(device_config, indent=2, ensure_ascii=False)}")
            
            # 标准化数据格式
            device_config = _normalize_device_config(device_config)
            app.logger.debug(f"标准化后的配置: {json.dumps(device_config, indent=2, ensure_ascii=False)}")
            
            device_name = device_config.get('name')
            if not device_name:
                return jsonify({
                    'success': False,
                    'error': '设备名称不能为空'
                }), 400
            
            from services.config_manager import ConfigManager
            
            config_manager = ConfigManager()
            
            # 加载现有设备列表
            existing_devices = config_manager.load_devices()
            
            # 验证单个设备配置
            validation_errors = config_manager.validate_devices_config([device_config])
            if validation_errors:
                app.logger.error(f"配置验证失败: {validation_errors}")
                return jsonify({
                    'success': False,
                    'error': '配置验证失败',
                    'details': validation_errors
                }), 400
            
            # 查找是否为更新现有设备
            device_index = -1
            for i, device in enumerate(existing_devices):
                if device.get('name') == device_name:
                    device_index = i
                    break
            
            # 更新或添加设备
            if device_index >= 0:
                existing_devices[device_index] = device_config
                operation = "更新"
            else:
                existing_devices.append(device_config)
                operation = "添加"
            
            # 保存到配置文件
            success = config_manager.save_devices(existing_devices)
            if not success:
                return jsonify({
                    'success': False,
                    'error': '保存配置文件失败'
                }), 500
            
            # 保存设备信息到数据库
            if storage_service:
                try:
                    device_info = {
                        'device_name': device_name,
                        'device_type': device_config.get('type'),
                        'description': device_config.get('description', ''),
                        'enabled': device_config.get('enabled', True),
                        'polling_interval': device_config.get('polling_interval', 1000),
                        'config_json': json.dumps(device_config.get('config', {})),
                        'points_count': len(device_config.get('points', [])),
                        'updated_at': datetime.now()
                    }
                    _save_device_to_database(device_info)
                    
                    # 保存数据点配置到数据库
                    points = device_config.get('points', [])
                    if points:
                        _save_device_points_to_database(device_name, points)
                        
                except Exception as db_error:
                    app.logger.warning(f"保存设备到数据库失败: {db_error}")
                    # 即使数据库保存失败，配置文件已保存成功，不影响主流程
            
            # 如果数据引擎存在，通知重新加载配置
            if data_engine:
                try:
                    # 实际创建设备驱动并添加到引擎
                    success = _create_and_add_device_to_engine(device_config)
                    if success:
                        app.logger.info(f"成功将设备 {device_name} 添加到数据引擎")
                    else:
                        app.logger.warning(f"将设备 {device_name} 添加到数据引擎失败")
                except Exception as add_error:
                    app.logger.error(f"添加设备到引擎失败: {add_error}")
                    
                try:
                    data_engine.reload_device_config(device_name)
                except Exception as reload_error:
                    app.logger.warning(f"重新加载设备配置失败: {reload_error}")
            
            return jsonify({
                'success': True,
                'message': f'设备配置 {device_name} {operation}成功',
                'operation': operation
            })
            
        except Exception as e:
            app.logger.error(f"保存设备配置异常: {e}")
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/device/<device_name>/deploy', methods=['POST'])
    def deploy_device(device_name: str):
        """部署设备配置"""
        try:
            if data_engine:
                # 这里应该实现设备部署逻辑
                # 比如重新加载设备配置并启动连接
                
                return jsonify({
                    'success': True,
                    'message': f'设备 {device_name} 部署成功'
                })
            else:
                return jsonify({
                    'success': False,
                    'error': '数据引擎未初始化'
                }), 503
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/device/<device_name>/latest')
    def get_device_latest_data(device_name: str):
        """获取设备最新数据"""
        try:
            if storage_service:
                latest_data = storage_service.get_latest_values(device_name=device_name)
                return jsonify({
                    'success': True,
                    'data': latest_data
                })
            else:
                return jsonify({
                    'success': False,
                    'error': '存储服务未初始化'
                }), 503
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/devices/config', methods=['GET'])
    def get_devices_config():
        """获取设备配置"""
        try:
            from services.config_manager import ConfigManager
            
            config_manager = ConfigManager()
            devices = config_manager.load_devices()
            
            return jsonify({
                'success': True,
                'devices': devices
            })
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/devices/config', methods=['POST'])
    def save_devices_config():
        """保存设备配置"""
        try:
            from services.config_manager import ConfigManager
            
            data = request.json
            if not data:
                return jsonify({
                    'success': False,
                    'error': '配置数据缺失'
                }), 400
            
            devices = data.get('devices', [])
            if not devices:
                return jsonify({
                    'success': False,
                    'error': '设备列表不能为空'
                }), 400
            
            config_manager = ConfigManager()
            
            # 验证配置
            validation_errors = config_manager.validate_devices_config(devices)
            if validation_errors:
                return jsonify({
                    'success': False,
                    'error': '配置验证失败',
                    'details': validation_errors
                }), 400
            
            # 保存配置文件
            success = config_manager.save_devices(devices)
            if not success:
                return jsonify({
                    'success': False,
                    'error': '保存配置文件失败'
                }), 500
            
            # 同步保存到数据库
            if storage_service:
                try:
                    for device in devices:
                        device_name = device.get('name')
                        if device_name:
                            # 保存设备基本信息
                            device_info = {
                                'device_name': device_name,
                                'device_type': device.get('type'),
                                'description': device.get('description', ''),
                                'enabled': device.get('enabled', True),
                                'polling_interval': device.get('polling_interval', 1000),
                                'config_json': json.dumps(device.get('config', {})),
                                'points_count': len(device.get('points', [])),
                                'updated_at': datetime.now()
                            }
                            _save_device_to_database(device_info)
                            
                            # 保存数据点配置
                            points = device.get('points', [])
                            if points:
                                _save_device_points_to_database(device_name, points)
                    
                    app.logger.info(f"成功同步 {len(devices)} 个设备到数据库")
                    
                except Exception as db_error:
                    app.logger.warning(f"同步设备到数据库失败: {db_error}")
                    # 配置文件已保存成功，数据库同步失败不影响主要功能
            
            return jsonify({
                'success': True,
                'message': f'设备配置保存成功，共 {len(devices)} 个设备',
                'devices_count': len(devices)
            })
                
        except Exception as e:
            app.logger.error(f"保存设备配置异常: {e}")
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/devices/config/validate', methods=['POST'])
    def validate_devices_config():
        """验证设备配置"""
        try:
            from services.config_manager import ConfigManager
            
            data = request.json
            if not data:
                return jsonify({
                    'success': False,
                    'error': '配置数据缺失'
                }), 400
            
            devices = data.get('devices', [])
            config_manager = ConfigManager()
            validation_errors = config_manager.validate_devices_config(devices)
            
            return jsonify({
                'success': len(validation_errors) == 0,
                'errors': validation_errors
            })
            
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/devices/config/backup', methods=['GET'])
    def get_config_backups():
        """获取配置备份列表"""
        try:
            from services.config_manager import ConfigManager
            
            config_manager = ConfigManager()
            backups = config_manager.get_backup_list()
            
            return jsonify({
                'success': True,
                'backups': backups
            })
            
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/devices/config/backup/<backup_filename>/restore', methods=['POST'])
    def restore_config_backup(backup_filename: str):
        """恢复配置备份"""
        try:
            from services.config_manager import ConfigManager
            
            config_manager = ConfigManager()
            success = config_manager.restore_from_backup(backup_filename)
            
            if success:
                return jsonify({
                    'success': True,
                    'message': '配置恢复成功'
                })
            else:
                return jsonify({
                    'success': False,
                    'error': '配置恢复失败'
                }), 500
                
        except Exception as e:
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/device/<device_name>/delete', methods=['DELETE'])
    def delete_device_config(device_name: str):
        """删除设备配置"""
        try:
            from services.config_manager import ConfigManager
            
            config_manager = ConfigManager()
            
            # 从配置文件中删除设备
            success = config_manager.delete_device(device_name)
            if not success:
                return jsonify({
                    'success': False,
                    'error': f'设备 {device_name} 不存在或删除失败'
                }), 404
            
            # 从数据库中删除设备
            if storage_service:
                try:
                    _delete_device_from_database(device_name)
                    app.logger.info(f"成功从数据库删除设备: {device_name}")
                except Exception as db_error:
                    app.logger.warning(f"从数据库删除设备失败: {db_error}")
                    # 配置文件已删除成功，数据库删除失败不影响主要功能
            
            # 如果数据引擎存在，通知停止设备连接
            if data_engine:
                try:
                    data_engine.remove_device(device_name)
                except Exception as remove_error:
                    app.logger.warning(f"停止设备连接失败: {remove_error}")
            
            return jsonify({
                'success': True,
                'message': f'设备 {device_name} 删除成功'
            })
            
        except Exception as e:
            app.logger.error(f"删除设备配置异常: {e}")
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.route('/api/device/<device_name>/info', methods=['GET'])
    def get_device_config_info(device_name: str):
        """获取设备配置详情（从数据库）"""
        try:
            # 从数据库获取设备信息
            device_info = _get_device_from_database(device_name)
            if not device_info:
                return jsonify({
                    'success': False,
                    'error': f'设备 {device_name} 不存在'
                }), 404
            
            # 获取数据点信息
            if storage_service and storage_service.sqlite_enabled:
                with storage_service.lock:
                    cursor = storage_service.sqlite_conn.execute('''
                        SELECT * FROM device_points WHERE device_name = ?
                        ORDER BY point_name
                    ''', (device_name,))
                    
                    points = []
                    for row in cursor.fetchall():
                        point_dict = dict(row)
                        # 解析报警配置
                        if point_dict.get('alarm_config'):
                            try:
                                point_dict['alarm_config'] = json.loads(point_dict['alarm_config'])
                            except:
                                point_dict['alarm_config'] = None
                        points.append(point_dict)
                    
                    device_info['points'] = points
            
            # 解析配置JSON
            if device_info.get('config_json'):
                try:
                    device_info['config'] = json.loads(device_info['config_json'])
                except:
                    device_info['config'] = {}
            
            return jsonify({
                'success': True,
                'data': device_info
            })
            
        except Exception as e:
            app.logger.error(f"获取设备配置详情异常: {e}")
            return jsonify({
                'success': False,
                'error': str(e)
            }), 500
    
    @app.errorhandler(404)
    def not_found(error):
        """404错误处理"""
        return jsonify({
            'success': False,
            'error': 'API接口未找到'
        }), 404
    
    @app.errorhandler(500)
    def internal_error(error):
        """500错误处理"""
        return jsonify({
            'success': False,
            'error': '服务器内部错误'
        }), 500

def _save_device_to_database(device_info: Dict[str, Any]):
    """保存设备信息到数据库"""
    try:
        if not storage_service or not storage_service.sqlite_enabled:
            return False
        
        with storage_service.lock:
            # 创建设备信息表（如果不存在）
            storage_service.sqlite_conn.execute('''
                CREATE TABLE IF NOT EXISTS device_configs (
                    device_name TEXT PRIMARY KEY,
                    device_type TEXT NOT NULL,
                    description TEXT,
                    enabled BOOLEAN DEFAULT TRUE,
                    polling_interval INTEGER DEFAULT 1000,
                    config_json TEXT,
                    points_count INTEGER DEFAULT 0,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
                )
            ''')
            
            # 保存或更新设备信息
            storage_service.sqlite_conn.execute('''
                INSERT OR REPLACE INTO device_configs 
                (device_name, device_type, description, enabled, polling_interval, 
                 config_json, points_count, updated_at, created_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, 
                        COALESCE((SELECT created_at FROM device_configs WHERE device_name = ?), ?))
            ''', (
                device_info['device_name'],
                device_info['device_type'],
                device_info['description'],
                device_info['enabled'],
                device_info['polling_interval'],
                device_info['config_json'],
                device_info['points_count'],
                device_info['updated_at'].isoformat(),
                device_info['device_name'],  # 用于查找现有记录的created_at
                device_info['updated_at'].isoformat()  # 新记录的created_at
            ))
            
            storage_service.sqlite_conn.commit()
            return True
            
    except Exception as e:
        logging.error(f"保存设备到数据库失败: {e}")
        return False

def _save_device_points_to_database(device_name: str, points: list):
    """保存设备数据点配置到数据库"""
    try:
        if not storage_service or not storage_service.sqlite_enabled:
            return False
        
        with storage_service.lock:
            # 创建数据点配置表（如果不存在）
            storage_service.sqlite_conn.execute('''
                CREATE TABLE IF NOT EXISTS device_points (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    device_name TEXT NOT NULL,
                    point_name TEXT NOT NULL,
                    description TEXT,
                    address TEXT,
                    data_type TEXT DEFAULT 'float',
                    access_type TEXT DEFAULT 'R',
                    unit TEXT,
                    topic TEXT,
                    alarm_enabled BOOLEAN DEFAULT FALSE,
                    alarm_config TEXT,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                    UNIQUE(device_name, point_name)
                )
            ''')
            
            # 删除旧的数据点配置
            storage_service.sqlite_conn.execute(
                'DELETE FROM device_points WHERE device_name = ?',
                (device_name,)
            )
            
            # 保存新的数据点配置
            for point in points:
                alarm_config = None
                if point.get('alarm', {}).get('enabled'):
                    alarm_config = json.dumps(point['alarm'])
                
                storage_service.sqlite_conn.execute('''
                    INSERT INTO device_points 
                    (device_name, point_name, description, address, data_type, 
                     access_type, unit, topic, alarm_enabled, alarm_config)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                ''', (
                    device_name,
                    point.get('name', ''),
                    point.get('description', ''),
                    point.get('address', point.get('node_id', '')),
                    point.get('data_type', 'float'),
                    point.get('access', 'R'),
                    point.get('unit', ''),
                    point.get('topic', ''),
                    point.get('alarm', {}).get('enabled', False),
                    alarm_config
                ))
            
            storage_service.sqlite_conn.commit()
            return True
            
    except Exception as e:
        logging.error(f"保存设备数据点到数据库失败: {e}")
        return False

def _get_device_from_database(device_name: str) -> Optional[Dict[str, Any]]:
    """从数据库获取设备信息"""
    try:
        if not storage_service or not storage_service.sqlite_enabled:
            return None
        
        with storage_service.lock:
            cursor = storage_service.sqlite_conn.execute('''
                SELECT * FROM device_configs WHERE device_name = ?
            ''', (device_name,))
            
            row = cursor.fetchone()
            if row:
                return dict(row)
            return None
            
    except Exception as e:
        logging.error(f"从数据库获取设备信息失败: {e}")
        return None

def _delete_device_from_database(device_name: str) -> bool:
    """从数据库删除设备"""
    try:
        if not storage_service or not storage_service.sqlite_enabled:
            return False
        
        with storage_service.lock:
            # 删除设备配置
            storage_service.sqlite_conn.execute(
                'DELETE FROM device_configs WHERE device_name = ?',
                (device_name,)
            )
            
            # 删除数据点配置
            storage_service.sqlite_conn.execute(
                'DELETE FROM device_points WHERE device_name = ?',
                (device_name,)
            )
            
            storage_service.sqlite_conn.commit()
            return True
            
    except Exception as e:
        logging.error(f"从数据库删除设备失败: {e}")
        return False

def _normalize_device_config(device_config: Dict[str, Any]) -> Dict[str, Any]:
    """标准化设备配置数据格式"""
    normalized = device_config.copy()
    
    # 处理数据点格式标准化
    if 'points' in normalized and normalized['points']:
        for point in normalized['points']:
            # 转换前端的dataType为后端的data_type
            if 'dataType' in point:
                point['data_type'] = point.pop('dataType')
            
            # 处理OPC UA节点ID
            if normalized.get('type') == 'opcua':
                # 如果node_id为空字符串，移除该字段（这会触发验证错误）
                if 'node_id' in point and point['node_id'] == '':
                    logging.warning(f"数据点 '{point.get('name')}' 的node_id为空字符串")
                    # 不删除，让验证器捕获这个错误
                # 如果没有node_id字段但有address字段，可能是前端Bug
                elif 'node_id' not in point and 'address' in point and point['address']:
                    logging.info(f"将数据点 '{point.get('name')}' 的address字段转换为node_id")
                    point['node_id'] = point.pop('address')
            
            # 处理MQTT主题
            elif normalized.get('type') == 'mqtt':
                if 'topic' in point and point['topic'] == '':
                    logging.warning(f"数据点 '{point.get('name')}' 的topic为空字符串")
            
            # 处理其他协议的地址
            else:
                if 'address' in point and point['address'] == '':
                    logging.warning(f"数据点 '{point.get('name')}' 的address为空字符串")
            
            # 确保所有数据点都有必要的字段
            if 'access' not in point:
                point['access'] = 'R'  # 默认只读
            if 'data_type' not in point:
                point['data_type'] = 'float'  # 默认浮点数
    
    return normalized 

def _create_and_add_device_to_engine(device_config: Dict[str, Any]) -> bool:
    """实际创建设备驱动并添加到引擎"""
    try:
        if not data_engine:
            return False
        
        device_name = device_config.get('name')
        device_type = device_config.get('type')
        config = device_config.get('config', {})
        points = device_config.get('points', [])
        
        if not device_name or not device_type:
            logging.error("设备名称或类型缺失")
            return False
        
        # 创建设备驱动实例
        driver = _create_device_driver(device_type, device_name, config, points)
        if not driver:
            return False
        
        # 移除已存在的设备（如果有）
        if device_name in data_engine.devices:
            data_engine.remove_device(device_name)
        
        # 添加新设备到引擎
        data_engine.add_device(device_name, driver)
        
        logging.info(f"成功创建并添加设备: {device_name} ({device_type})")
        return True
        
    except Exception as e:
        logging.error(f"创建设备驱动失败: {e}")
        return False

def _create_device_driver(device_type: str, device_name: str, config: Dict[str, Any], points: List[Dict[str, Any]]):
    """创建设备驱动实例"""
    try:
        # 准备驱动配置
        driver_config = {
            'name': device_name,
            'type': device_type,
            'config': config,
            'points': points
        }
        
        if device_type == 'modbus':
            from core.drivers.modbus import ModbusDriver
            return ModbusDriver(driver_config)
        elif device_type == 's7':
            from core.drivers.s7 import S7Driver
            return S7Driver(driver_config)
        elif device_type == 'opcua':
            from core.drivers.opcua import OpcuaDriver
            return OpcuaDriver(driver_config)
        elif device_type == 'mqtt':
            from core.drivers.mqtt import MqttDriver
            return MqttDriver(driver_config)
        else:
            logging.error(f"不支持的设备类型: {device_type}")
            return None
            
    except ImportError as e:
        logging.error(f"导入驱动模块失败: {e}")
        return None
    except Exception as e:
        logging.error(f"创建驱动实例失败: {e}")
        return None 